using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace PageDraw
{
    public class GraphicsTreeMgr
    {
        private GraphicsTree tree;
        private DrawArea drawArea;

        public GraphicsTreeMgr(GraphicsTree tree, DrawArea drawArea) 
        {
            this.tree = tree;
            this.drawArea = drawArea;
        }

        public void SetSingleSelection(Point point)
        {
            ClearSelectedDrawObject();
            for (int i = tree.DrawObjects.Count - 1; i >= 0; i--)
            {
                DrawObject obj = tree.DrawObjects[i].Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.GetRect().Contains(point))
                    {
                        obj.SetSelected(true);
                        drawArea.SetPropGridSelectedObject(obj);

                        drawArea.Refresh();
                        break;
                    }
                }
            }
        }

        public bool SetDrawObjectSelection(Point point, bool isCtrlDown)
        {
            bool flg = false;
            int selectCount = 0;
            if (!isCtrlDown)
            {
                ClearSelectedDrawObject();
            }
            for (int i = tree.DrawObjects.Count - 1; i >= 0; i--)
            {
                DrawObject obj = tree.DrawObjects[i].Tag as DrawObject;
                if (obj != null)
                {
                    bool val = (obj.GetRect().Contains(point));
                    if (val)
                    {
                        if (!isCtrlDown)
                        {
                            ClearSelectedDrawObject();
                        }
                        obj.SetSelected(val);
                        drawArea.SetPropGridSelectedObject(obj);
                    }
                    if (val)
                    {
                        flg = val;
                        selectCount++;
                        Rectangle rect = obj.GetRect();
                        foreach (TreeNode node in tree.DrawObjects)
                        {
                            DrawObject o = node.Tag as DrawObject;
                            if (o != null)
                            {
                                if (obj != o && rect.Contains(o.GetRect()))
                                {
                                    selectCount++;
                                    o.SetSelected(true);
                                }
                            }
                        }
                        break;
                    }
                }
            }
            if (!flg)
            {
                drawArea.SetPropGridSelectedObject(NoPropertyObject.GetInstance());
            }
            return flg;
        }

        public bool IsPointOnHandle(Point point)
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsPointOnHandle(point))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public void ClearSelectedDrawObject()
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    obj.SetSelected(false);
                }
            }
        }

        public void ResetSelectedDrawObjectLorS(Point msLocation, Point point)
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        obj.ResetLorS(msLocation, point);
                        drawArea.SetPropGridSelectedObject(obj);
                    }
                }
            }
        }
       
        public void ResetSelectedDrawObjectL(int dx, int dy)
        {
            bool isFisrt = true;
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        obj.ResetL(dx, dy);
                        if (isFisrt)
                        {
                            drawArea.SetPropGridSelectedObject(obj);
                            isFisrt = false;
                        }
                    }
                }
                
            }
        }

        public void DeleteSelectedDrawObjects()
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        node.Tag = null;
                    }
                }
            }
            drawArea.Refresh();
        }

        public void MultiSeletecedDrawObject(Rectangle sectionRect)
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                { 
                    if(sectionRect.Contains(obj.GetRect()))
                    {
                        obj.SetSelected(true);
                    }
                }
            }
        }

        public void AlignHandle(Align align)
        {
            List<DrawObject> sobjs = new List<DrawObject>();
            int nx = 0;
            int ny = 0;
            bool isFirst = true;
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        sobjs.Add(obj);
                        if (isFirst)
                        {
                            nx = obj.X;
                            ny = obj.Y;
                            isFirst = false;
                        }
                        else
                        {
                            if (align == Align.UP)
                            {
                                if (obj.Y < ny)
                                {
                                    ny = obj.Y;
                                }
                            }
                            else if (align == Align.Down)
                            {
                                if (obj.Y > ny)
                                {
                                    ny = obj.Y;
                                }
                            }
                            else if (align == Align.Left)
                            {
                                if (obj.X < nx)
                                {
                                    nx = obj.X;
                                }
                            }
                            else if (align == Align.Right)
                            {
                                if (obj.X > nx)
                                {
                                    nx = obj.X;
                                }
                            }
                        }
                    }
                }
            }

            foreach (DrawObject obj in sobjs)
            {
                if (align == Align.UP || align == Align.Down)
                {
                    obj.Y = ny;
                }
                else if (align == Align.Left || align == Align.Right)
                {
                    obj.X = nx;
                }
                drawArea.Refresh();
            }
        }

        public void SelectAll()
        {
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    obj.SetSelected(true);
                }
            }
            drawArea.Refresh();
        }

        private List<DrawObject> copyObjs = new List<DrawObject>();

        public void CopyObjects()
        {
            copyObjs.Clear();
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        DrawObject newObj = obj.Clone() as DrawObject;
                        if (newObj != null)
                        {
                            newObj.ProduceID();
                            newObj.X += 10;
                            newObj.Y += 10;
                            copyObjs.Add(newObj);
                        }
                    }
                }
            }
        }

        private List<DrawObject> rCopyObjs = new List<DrawObject>();

        public void PasteObjects()
        {
            rCopyObjs.Clear();
            foreach (DrawObject obj in copyObjs)
            {
                tree.AddDrawObject(obj);
                DrawObject newObj = obj.Clone() as DrawObject;
                if (newObj != null)
                {
                    newObj.ProduceID();
                    newObj.X += 10;
                    newObj.Y += 10;
                    rCopyObjs.Add(newObj);
                }
            }
            copyObjs.Clear();
            copyObjs.AddRange(rCopyObjs);
            drawArea.Refresh();
        }

        public void DirectionMove(Direction direction)
        {
            List<DrawObject> sobjs = new List<DrawObject>();
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        sobjs.Add(obj);
                        node.Tag = null;
                    }
                }
            }
            if (direction == Direction.Front)
            {
                foreach (DrawObject obj in sobjs)
                {
                    tree.AddDrawObject(obj);
                }
            }
            else if (direction == Direction.Back)
            {
                foreach (DrawObject obj in sobjs)
                {
                    tree.InsertDrawObject(obj);
                }
            }
            drawArea.Refresh();
        }

        public void CutObjects()
        {
            copyObjs.Clear();
            foreach (TreeNode node in tree.DrawObjects)
            {
                DrawObject obj = node.Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.IsSelected())
                    {
                        DrawObject newObj = obj.Clone() as DrawObject;
                        if (newObj != null)
                        {
                            newObj.X += 10;
                            newObj.Y += 10;
                            copyObjs.Add(newObj);
                            node.Tag = null;
                        }
                    }
                }
            }
            drawArea.Refresh();
        }

        public bool SaveToXML(string filePath)
        {
            XMLHandler xml = new XMLHandler();
            xml.ProduceXml(filePath, tree);
            return true;
        }

        public bool SaveToObj(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.SetAttributes(filePath, FileAttributes.Normal);
                }
                using (Stream stream = File.Create(filePath))
                {
                    IFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(stream, tree.DrawObjects);
                    File.SetAttributes(filePath, FileAttributes.ReadOnly);
                    return true;
                }
            }
            catch (Exception)
            {
                File.SetAttributes(filePath, FileAttributes.ReadOnly);
                return false;
            }
        }

        public bool OpenFronObj(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.SetAttributes(filePath, FileAttributes.Normal);
                }
                using (Stream stream = File.Open(filePath, FileMode.Open))
                {
                    IFormatter formatter = new BinaryFormatter();
                    List<TreeNode> objs = formatter.Deserialize(stream) as List<TreeNode>;
                    if (objs != null)
                    {
                        tree.DrawObjects = objs;
                        drawArea.Refresh();
                        File.SetAttributes(filePath, FileAttributes.ReadOnly);
                        return true;
                    }
                    else
                    {
                        File.SetAttributes(filePath, FileAttributes.ReadOnly);
                        return false;
                    }
                }
            }
            catch (Exception)
            {
                File.SetAttributes(filePath, FileAttributes.ReadOnly);
                return false;
            }
        }

        public bool AddEvent(Point point)
        {
            bool flg = false;
            for (int i = tree.DrawObjects.Count - 1; i >= 0; i--)
            {
                DrawObject obj = tree.DrawObjects[i].Tag as DrawObject;
                if (obj != null)
                {
                    if (obj.GetRect().Contains(point))
                    {
                        if (obj is DrawJButton)
                        {
                            DrawJButton btn = obj as DrawJButton;
                            string btnId = btn.Id.Trim();
                            if (!String.IsNullOrEmpty(btnId))
                            {
                                flg = true;
                                btn.ActionListener = btnId.Substring(0, 1).ToUpper() + btnId.Substring(1) + "Action";
                                drawArea.SetPropGridSelectedObject(obj);
                            }
                        }
                    }
                }
            }
            return flg;
        }
    }
}
